var Fiber = require('fibers');
Fiber(function() {

    require("../../server/appInit");
    var MongoClient = require('mongodb').MongoClient;
    var EventEmitter = require('events').EventEmitter;
    var fs = require('fs');

    //获取出历史数据版本的名字
    var col_names = fs.existsSync(__dirname + "/.db/mongodb_names.json") ? require("./.db/mongodb_names.json") : [];
    var col_name = col_names[0];

    var connect = function() {
        var fiber = Fiber.current;
        var _err;
        var _res;
        MongoClient.connect('mongodb://127.0.0.1:27017/' + col_name, function(err, db) {
            _err = err;
            _res = db;
            fiber.run();
        });
        Fiber.yield(); //挂起
        if (_err) {
            throw _err;
        }
        return _res
    };

    var mon_db = {
        _isConnectAble: function() {
            try {
                var db = connect();
                return true;
            } catch (e) {
                return false;
            }
        },
        _updateCache: function(fileName) { //更新缓存到文件中进行备份
            var db = connect();
            var fiber = Fiber.current;
            var _err;
            var _res;
            db.collectionNames(function(err, names) {
                _err = err;
                _res = names;
                db.close();
                fiber.run();
            });
            Fiber.yield(); //挂起
            if (_err) {
                throw _err;
            }
            var _db = {};
            _res.forEach(function(item) {
                var name = item.name.substr(col_name.length + 1);
                if (name !== "system.indexes") {
                    _db[name] = mon_db.find_all(name);
                }
            });
            console.time("update_data");
            var _data = JSON._stringify(_db)
            if (_data) {
                fileName || (fileName = "data.bak." + (new Date).format("yyyy_MM_dd_HH_mm") + ".json");
                require("fs").writeFileSync(__dirname + "/.db/" + fileName, _data);
            }
            console.timeEnd("update_data");
        },
        _getCollection: function(db_name) {
            db_name = db_name.toLowerCase();
            var db = connect();
            var col = db.collection(db_name);
            col.close = function() {
                db.close()
            };
            return col;
        },
        insert: function(db_name, obj, index) {
            var collection = mon_db._getCollection(db_name);
            var fiber = Fiber.current;
            var _err;
            obj._id || (obj._id = index);
            if (mon_db.find_by_id(db_name, obj._id)) { //如果已经是有存在的数据了转为使用update
                collection.close();
                mon_db.update(db_name, obj._id, obj);
                return;
            }
            // console.log("INSERT:", obj);
            collection.insert(obj, function(err, result) {
                // console.log(result);
                mon_db.emit("insert", db_name.toLowerCase(), obj);
                _err = err;
                fiber.run();
            });
            Fiber.yield(); //挂起
            collection.close();
            if (_err) {
                throw _err;
            }
        },
        find_by_id: function(db_name, id) {
            var collection = mon_db._getCollection(db_name);
            var fiber = Fiber.current;
            var _err;
            var _res;
            collection.findOne({
                _id: id
            }, function(err, result) {
                _err = err;
                _res = result;
                fiber.run();
            });
            Fiber.yield(); //挂起
            collection.close();
            if (_err) {
                throw _err;
            }
            return _res;
        },
        find_one: function(db_name, obj) {
            console.log("find")
            var collection = mon_db._getCollection(db_name);
            var fiber = Fiber.current;
            var _err;
            var _res;
            collection.findOne(mon_db._obj_flat(obj), function(err, result) {
                _err = err;
                _res = result;
                fiber.run();
            });
            Fiber.yield(); //挂起
            collection.close();
            if (_err) {
                throw _err;
            }
            return _res;
        },
        find_last_one: function(db_name, obj, sort_key, no_asc) {
            var collection = mon_db._getCollection(db_name);
            var fiber = Fiber.current;
            var _err;
            var _res;
            var _sort = {};
            //升序为1，倒序为-1，默认为倒序：大>小
            _sort[sort_key] = (!no_asc) ? -1 : 1;
            collection.find(mon_db._obj_flat(obj)).sort(_sort).toArray(function(err, result) {
                _err = err;
                _res = result[0];
                fiber.run();
            });
            Fiber.yield(); //挂起
            collection.close();
            if (_err) {
                throw _err;
            }
            return _res;
        },
        find_list: function(db_name, obj, num) {
            var collection = mon_db._getCollection(db_name);
            var fiber = Fiber.current;
            var _err;
            var _res;
            collection.find(mon_db._obj_flat(obj)).toArray(function(err, result) {
                _err = err;
                _res = result;
                fiber.run();
            });
            Fiber.yield(); //挂起
            collection.close();
            if (_err) {
                throw _err;
            }
            return _res;
        },
        find_all: function(db_name) {

            return mon_db.find_list(db_name, {});
        },
        update: function(db_name, obj_index, obj) {
            var collection = mon_db._getCollection(db_name);
            var fiber = Fiber.current;
            var _err;
            var _res
            var _id_bak;
            (_id_bak = obj._id) && (delete obj._id); //UPDATE 命令不能有ID在，临时删除
            collection.update({
                _id: obj_index
            }, {
                $set: obj
            }, function(err, result) {
                _err = err;
                _res = result;
                fiber.run();
            });
            Fiber.yield(); //挂起
            collection.close();
            if (_err) {
                throw _err;
            }
            //还原ID
            obj._id = _id_bak;
            if (_res === 0) {
                console.log("修改", db_name, obj_index, "时，0行受影响，转成插入模式");
                mon_db.insert(db_name, obj, obj_index);
            }
        },
        remove: function(db_name, obj_index) {
            var collection = mon_db._getCollection(db_name);
            var fiber = Fiber.current;
            var _err;
            collection.remove({
                _id: obj_index
            }, function(err, result) {
                _err = err;
                if (result === 0) {
                    console.info("要移除的对象不存在：", db_name, obj_index);
                }
                fiber.run();
            });
            Fiber.yield(); //挂起
            collection.close();
            if (_err) {
                throw _err;
            }
        },
        remove_list: function(db_name, obj) {
            var collection = mon_db._getCollection(db_name);
            var fiber = Fiber.current;
            var _err;
            collection.remove(obj, function(err, result) {
                _err = err;
                if (result === 0) {
                    console.info("要移除的对象不存在：", db_name, obj);
                }
                fiber.run();
            });
            Fiber.yield(); //挂起
            collection.close();
            if (_err) {
                throw _err;
            }
        },
        refreshIndex: function(fileName) {
            fileName || (fileName = "data.cache.json");
            //如果存在文件版本的数据库，则使用这个数据库，并导入到新的数据集
            if (fs.existsSync(__dirname + "/.db/" + fileName) && !fs.existsSync(__dirname + "/.db/.file.db.lock")) {
                console.log("发现文件版数据库");
                var _db = require("./.db/data.cache.json");
                col_name = "O2O_" + (new Date).format("yyyy_MM_dd_HH_mm");
                console.log("使用新的数据集：", col_name);
                col_names.unshift(col_name);
                fs.writeFileSync(__dirname + "/.db/mongodb_names.json", JSON.stringify(col_names));
                console.log("开始录入文件数据");
                for (var db_name in _db) {
                    if (_db.hasOwnProperty(db_name)) {
                        //并不会触发对应的emit事件，因为db还没有exports出去，不会有注册的事件
                        console.log("表", db_name, "录入，共", _db[db_name].length, "条数据");
                        mon_db.insert(db_name, _db[db_name])
                    }
                }
                // fs.renameSync(__dirname + "/.db/data.cache.json", __dirname + "/.db/data.cache.to_" + col_name + ".json")
                fs.writeFileSync(__dirname + "/.db/.file.db.lock", "");
            } else {
                console.log("使用现有数据集：", col_name);
            }
        },
        bak: function() {
            //文件备份
            fs.renameSync(__dirname + "/.db/data.cache.json", __dirname + "/.db/data.cache.to_O2O_" + (new Date).format("yyyy_MM_dd_HH_mm") + ".json")
            mon_db._updateCache("data.cache.json");
        },
        removeLock: function() {
            fs.existsSync(__dirname + "/.db/.file.db.lock") && fs.unlinkSync(__dirname + "/.db/.file.db.lock");
        },
        _sortBy: require("./skill").sortBy,
        _obj_flat: function(obj) {
            var result = {};
            for (var i in obj) {
                var v = obj[i];
                if (typeof v === "object" && !Array.isArray(v)) {
                    var _flat_v = mon_db._obj_flat(v);
                    for (var ii in _flat_v) {
                        result[i + "." + ii] = _flat_v[ii];
                    }
                } else {
                    result[i] = v
                }
            }
            return result;
        }
    };

    mon_db.__proto__ = EventEmitter.prototype;
    EventEmitter.call(mon_db);
    module.exports = mon_db;


    // var admin = mon_db.find_one("admin", {
    //     "info.password": "88d299247c862cd20c766272686695a6ecb653b3a30569c73f31c79485b3afb8"
    // });
    // console.log(admin);
    // console.log(mon_db._obj_flat({
    //     info: {
    //         name: "gaubee",
    //         per: {
    //             can_do: false
    //         }
    //     },
    //     config: {
    //         pics: [1, 2, 3]
    //     },
    //     age: 10
    // }));
    // setInterval(function() {
    //     mon_db._updateCache();
    // }, 60 * 1000 * 30); //半小时进行一次备份

    // var bus = mon_db.find_one("O2O_2015_01_28_15_09.bus",{});
    // console.log(bus);

    /*TEST insert*/
    //插到队伍末尾
    // var _id = "U_Bangeel_xxxxx1" //+ Math.random().toString(32).substr(2);
    // mon_db.insert("user", {
    //     _id: _id,
    //     info: {
    //         name: "Bangeel"
    //     },
    //     create_time: +new Date
    // }, "U_Gaubee");

    /*TEST find_list*/
    // var gaubees = mon_db.find_list("user",{
    //     info:{
    //         name:"Bangeel"
    //     }
    // });
    // console.log(gaubees);

    /*TEST find_all*/
    // var users = mon_db.find_all("user");
    // console.log(users);

    /*TEST remove*/
    // mon_db.insert("user", {
    //     _id: "U_Bangeel_test_for_remove",
    //     info: {
    //         name: "Bangeel"
    //     },
    //     create_time: +new Date
    // });
    // mon_db.remove("user", "U_Bangeel_test_for_remove");
    // var users = mon_db.find_all("user");
    // console.log(users);

    /*TEST remove_list*/
    // mon_db.insert("user", {
    //     _id: "U_Bangeel_test_for_remove",
    //     info: {
    //         name: "Bangeel_test"
    //     },
    //     create_time: +new Date
    // });
    // mon_db.insert("user", {
    //     _id: "U_Bangeel_test_for_remove2",
    //     info: {
    //         name: "Bangeel_test"
    //     },
    //     create_time: +new Date
    // });
    // mon_db.remove_list("user", {
    //     info: {
    //         name: "Bangeel"
    //     }
    // });
    // var users = mon_db.find_all("user");
    // console.log(users);

    /*TEST find_one*/
    // var me = mon_db.find_one("user", {
    //     info: {
    //         name: "Bangeel"
    //     }
    // });
    // console.log(me);

    /*TEST find_by_id*/
    // var me = mon_db.find_by_id("user", "U_1178371c14b2566216a");
    // console.log(me);

    /*TEST find_last_one*/
    // var me = mon_db.find_last_one("visitorinfo", {
    //     bus_id: "www",
    //     user_ip: "127.0.0.1"
    // }, "begin_visit_time");
    // console.log(me);

    /*TEST update*/
    // var data = {
    //     type: 'bus',
    //     folder_name: 'B_8509345e14b3efd8935',
    //     _his: [],
    //     info: {
    //         name: 'testhehehe4',
    //         title: 'testhehehe',
    //         address: '',
    //         email: 'testhehehe4@qq.com',
    //         mobile_phone: '18850888894',
    //         intro: 'testhehehe',
    //         store_imgs: [],
    //         logo_url: '',
    //         logistics: '',
    //         open_time: {
    //             s_hour: 8,
    //             s_min: 0,
    //             e_hour: 23,
    //             e_min: 0
    //         },
    //         qq: '',
    //         alipay: {
    //             partner: undefined,
    //             key: undefined,
    //             seller_email: undefined
    //         },
    //         tenpay: {
    //             appid: undefined,
    //             key: undefined
    //         },
    //         version: 'std',
    //         way: '',
    //         password: '2a78add5a131b6e60523eec40aa235ee859d18602cedbc7fca401315e76cd4e4'
    //     },
    //     _id: 'testhehehe4',
    //     store: [],
    //     ach: [],
    //     comments: [],
    //     replys: [],
    //     tags: [],
    //     classifys: [],
    //     league: null,
    //     status: 0,
    //     buffs: [],
    //     recommend_buffs: [{
    //         max_price: 1000,
    //         rate: 0.2
    //     }],
    //     recommend_config: [],
    //     recommend_discount: 0,
    //     recommend_config_buff_id: null,
    //     guide_config: [],
    //     guide_config_buff_id: null,
    //     guide_list: [],
    //     config: {},
    //     create_time: 1422690978388,
    //     expiration_time: 1422690978388,
    //     user_id: null,
    //     has_add_expiration_time: false
    // };
    // mon_db.refreshIndex();
    // mon_db.update("user", "testhehehe4", data);
    // var users = mon_db.find_by_id("user", "testhehehe4");
    // console.log(users);
    // mon_db.remove("user","testhehehe4");
}).run();